package net.uzen.office.flickr;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.MessageDigest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;

import net.uzen.office.article.model.Article;
import net.uzen.office.common.UzenOfficeConstants;
import net.uzen.office.common.controller.BaseController;
import net.uzen.office.common.model.SessionInfo;
import net.uzen.office.common.util.SessionUtil;
import net.uzen.office.flickr.model.FlickrModel;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.aetrion.flickr.Flickr;
import com.aetrion.flickr.FlickrException;
import com.aetrion.flickr.REST;
import com.aetrion.flickr.RequestContext;
import com.aetrion.flickr.auth.Auth;
import com.aetrion.flickr.auth.AuthInterface;
import com.aetrion.flickr.auth.Permission;

public class FlickrController extends BaseController {

	private static final Log logger = LogFactory.getLog(FlickrController.class);

	private static final String API_KEY = "03f3fab85e2cd28de1fb969b320768bc";
	private static final String SECRET_KEY = "8c7381558956a210";
	private static final String FROB = "72157623003764474-11586ecad2390b70-35662527";

	public ModelAndView test(HttpServletRequest request,
			HttpServletResponse response) {
		String frob = request.getParameter("frob");
		logger.debug("[!] frob : " + frob);

		ModelAndView mav = new ModelAndView();

		mav.addObject("API_KEY", API_KEY);
		mav.addObject("SECRET_KEY", SECRET_KEY);

		if (StringUtils.isNotEmpty(frob)) {
			mav.addObject("frob", frob);
		}

		return mav;

	}

	public ModelAndView uploadPhoto2(HttpServletRequest request,
			HttpServletResponse response, Article article) {
		// API 키 값들
		String API_KEY = "03f3fab85e2cd28de1fb969b320768bc";
		String SECRET = "8c7381558956a210";
		String PERMS = "write";
		String METHOD = "flickr.auth.getFrob";

		String apiSig = SECRET + "api_key" + API_KEY + "method" + METHOD
				+ "perms" + PERMS;

		String hexString = getMD5Hash(apiSig);

		// URL 셋팅
		String url = "http://flickr.com/services/rest/?api_key=" + API_KEY
				+ "&method=" + METHOD + "&api_sig=" + hexString + "&perms="
				+ PERMS;

		// HttpClient 설정
		HttpClient httpClient = new HttpClient();
		httpClient.getParams().setParameter("http.protocol.element-charset",
				"UTF-8");
		httpClient.getParams().setParameter("http.protocol.content-charset",
				"UTF-8");

		// GetMethod 설정
		GetMethod getMethod = new GetMethod(url);

		try {
			// HttpClient 를 통해 GetMethod 를 실행
			int result = httpClient.executeMethod(getMethod);

			// TODO : HttpStatus 를 비교
			if (result > 0) {

				// Get the response body
				InputStream rstream = getMethod.getResponseBodyAsStream();

				// Document 구조로 읽어와 원하는 노드를 찾기 위해 Parsing
				Document responseD = DocumentBuilderFactory.newInstance()
						.newDocumentBuilder().parse(rstream);
				NodeList frobResponse = responseD.getElementsByTagName("frob");

				// Token을 가져오기 위한 frob 값 선언
				String frob = null;

				// frob 태그 안의 값을 가져온다.
				Node frobNode = frobResponse.item(0);

				// frob 노드가 null 이 아닐 경우에
				if (frobNode != null) {
					// frob 에 값을 셋팅한다.
					frob = frobResponse.item(0).getTextContent();
					logger.debug("[!] Successfully retrieved frob: " + frob);

					// frob 를 토큰으로 바꿔오는 작업
					String METHOD_CONVERT = "flickr.auth.getToken";
					apiSig = SECRET + "api_key" + API_KEY + "frob" + frob
							+ "method" + METHOD_CONVERT;

					// URL 셋팅
					url = "http://flickr.com/services/rest/?method="
							+ METHOD_CONVERT + "&api_key=" + API_KEY + "&frob="
							+ frob + "&api_sig=" + getMD5Hash(apiSig);
					logger.debug("[!!] URL >> " + url);

					// GetMethod 설정
					getMethod = new GetMethod(url);

					// HttpClient 를 통해 GetMethod 를 실행
					result = httpClient.executeMethod(getMethod);

					// TODO : HttpStatus 를 비교
					if (result > 0) {

						// Get the response body
						rstream = getMethod.getResponseBodyAsStream();
						logger.debug(" >> getResponseBodyAsString() > "
								+ getMethod.getResponseBodyAsString());
						logger.debug("[!] rstream >> " + rstream);

						// Document 구조로 읽어와 원하는 노드를 찾기 위해 Parsing
						responseD = DocumentBuilderFactory.newInstance()
								.newDocumentBuilder().parse(rstream);
						NodeList tokenResponse = responseD
								.getElementsByTagName("token");

						// authorizaion 가져오기 위한 token 값 선언
						String token = null;

						// token 태그 안의 값을 가져온다.
						Node tokenNode = frobResponse.item(0);
						// token 노드가 null 이 아닐 경우에
						if (tokenNode != null) {
							// frob 에 값을 셋팅한다.
							token = tokenResponse.item(0).getTextContent();
							logger.debug("[!] Successfully retrieved token : "
									+ token);
						}
					}
				} else {
					logger.error(responseD);
				}
			}
		} catch (Exception e) {
			logger.error(e);
		}

		return new ModelAndView();
	}

	private String getMD5Hash(String string) {
		StringBuilder hexString = new StringBuilder();
		try {
			// MD5 해시 값 가져오기
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(string.getBytes());
			byte[] digested = md.digest();

			// byte[] to Hex
			for (int i = 0; i < digested.length; i++) {
				hexString.append(Integer.toHexString(0xFF & digested[i])
						.length() == 0 ? 00 : Integer.toHexString(
						0xFF & digested[i]).length() == 1 ? "0"
						+ Integer.toHexString(0xFF & digested[i]) : Integer
						.toHexString(0xFF & digested[i]));
			}
		} catch (Exception e) {
			logger.error(e);
		}
		return hexString.toString();
	}

	public void test2(HttpServletRequest request, HttpServletResponse response) {
		logger.debug(" >> [!] test2.jude");

		// API 키 값들
		String API_KEY = "03f3fab85e2cd28de1fb969b320768bc";
		String SECRET = "8c7381558956a210";
		String PERMS = "write";
		String METHOD = "flickr.auth.getFrob";

		String apiSig = SECRET + "api_key" + API_KEY + "perms" + PERMS;

		// URL 셋팅
		String url = "http://flickr.com/services/auth/?api_key=" + API_KEY
				+ "&perms=" + PERMS + "&api_sig=" + getMD5Hash(apiSig);

		logger.debug(" >> [!] URL : " + url);

		// HttpClient 설정
		HttpClient httpClient = new HttpClient();
		httpClient.getParams().setParameter("http.protocol.element-charset",
				"UTF-8");
		httpClient.getParams().setParameter("http.protocol.content-charset",
				"UTF-8");

		// GetMethod 설정
		GetMethod getMethod = new GetMethod(url);

		try {
			// HttpClient 를 통해 GetMethod 를 실행
			int result = httpClient.executeMethod(getMethod);

			// TODO : HttpStatus 를 비교
			if (result > 0) {
				// Get the response body
				InputStream rstream = getMethod.getResponseBodyAsStream();

				// Document 구조로 읽어와 원하는 노드를 찾기 위해 Parsing
				Document responseD = DocumentBuilderFactory.newInstance()
						.newDocumentBuilder().parse(rstream);
				NodeList frobResponse = responseD.getElementsByTagName("frob");

				// frob 태그 안의 값을 가져온다.
				Node frobNode = frobResponse.item(0);

				// frob 노드가 null 이 아닐 경우에
				if (frobNode != null) {
					// frob 에 값을 셋팅한다.
					response.setContentType("text/plain; charset=UTF-8");
					response.getOutputStream().write(
							frobResponse.item(0).getTextContent().getBytes());
				}

			}
		} catch (Exception e) {
			logger.error(e);
		}

		// // Get the response body
		// InputStream rstream = getMethod.getResponseBodyAsStream();
		//
		// // Document 구조로 읽어와 원하는 노드를 찾기 위해 Parsing
		// Document responseD = DocumentBuilderFactory.newInstance()
		// .newDocumentBuilder().parse(rstream);
		// NodeList frobResponse = responseD.getElementsByTagName("frob");
		//
		// // Token을 가져오기 위한 frob 값 선언
		// String frob = null;
		//
		// // frob 태그 안의 값을 가져온다.
		// Node frobNode = frobResponse.item(0);
		//
		// // frob 노드가 null 이 아닐 경우에
		// if (frobNode != null) {
		// // frob 에 값을 셋팅한다.
		// frob = frobResponse.item(0).getTextContent();
		// logger.debug("[!] Successfully retrieved frob: " + frob);
	}

	public void getFrob(HttpServletRequest request, HttpServletResponse response) {
		logger.debug(" >> [!] getFrob.jude");

		// API 키 값들
		String METHOD = "flickr.auth.getFrob";

		// frob 를 토큰으로 바꿔오는 작업
		String apiSig = SECRET_KEY + "api_key" + API_KEY + "method" + METHOD;

		logger.debug(" >> [!] apiSig : " + apiSig);

		// URL 셋팅
		String url = "http://flickr.com/services/rest/?api_key=" + API_KEY
				+ "&method=" + METHOD + "&api_sig=" + getMD5Hash(apiSig);

		logger.debug(" >> [!] URL >> " + url);

		// HttpClient 설정
		HttpClient httpClient = new HttpClient();
		httpClient.getParams().setParameter("http.protocol.element-charset",
				"UTF-8");
		httpClient.getParams().setParameter("http.protocol.content-charset",
				"UTF-8");

		// GetMethod 설정
		GetMethod getMethod = new GetMethod(url);

		try {
			// HttpClient 를 통해 GetMethod 를 실행
			int result = httpClient.executeMethod(getMethod);

			// TODO : HttpStatus 를 비교
			if (result > 0) {
				// Get the response body
				InputStream rstream = getMethod.getResponseBodyAsStream();

				// Document 구조로 읽어와 원하는 노드를 찾기 위해 Parsing
				Document responseD = DocumentBuilderFactory.newInstance()
						.newDocumentBuilder().parse(rstream);
				NodeList frobResponse = responseD.getElementsByTagName("frob");

				// frob 태그 안의 값을 가져온다.
				Node frobNode = frobResponse.item(0);

				// frob 노드가 null 이 아닐 경우에
				if (frobNode != null) {
					// frob 에 값을 셋팅한다.
					logger.debug(" >> [!] item : "
							+ frobResponse.item(0).getTextContent());

					String frob = frobResponse.item(0).getTextContent();

					String authApiSig = SECRET_KEY + "api_key" + API_KEY
							+ "frob" + frob + "permswrite";

					String authUrl = "http://flickr.com/services/auth/?api_key="
							+ API_KEY
							+ "&frob="
							+ frob
							+ "&perms=write&api_sig=" + getMD5Hash(authApiSig);

					logger.debug(" >> [!] authUrl : " + authUrl);

					response.setContentType("text/plain; charset=UTF-8");
					response.getOutputStream().write(authUrl.getBytes());
				}
			}
		} catch (Exception e) {
			logger.error(e);
		}
	}

	Flickr f;
	RequestContext requestContext;
	String frob = "";
	String token = "";

	public void testAuth(HttpServletRequest request,
			HttpServletResponse response) {
		try {
			f = new Flickr(API_KEY, SECRET_KEY, new REST());
			Flickr.debugStream = false;
			requestContext = RequestContext.getRequestContext();
			AuthInterface authInterface = f.getAuthInterface();

			try {
				frob = authInterface.getFrob();
			} catch (FlickrException e) {
				e.printStackTrace();
			}
			System.out.println("frob: " + frob);
			URL url = authInterface.buildAuthenticationUrl(Permission.DELETE,
					frob);
			System.out
					.println("Press return after you granted access at this URL:");
			System.out.println(url.toExternalForm());

			// HttpClient 설정
			HttpClient httpClient = new HttpClient();
			httpClient.getParams().setParameter(
					"http.protocol.element-charset", "UTF-8");
			httpClient.getParams().setParameter(
					"http.protocol.content-charset", "UTF-8");

			String authApiSig = SECRET_KEY + "api_key" + API_KEY + "frob"
					+ frob + "permswrite";

			String url2 = "http://www.flickr.com/services/auth/";
			PostMethod postMethod = new PostMethod(url2);
			postMethod.addParameter("api_key", API_KEY);
			postMethod.addParameter("perms", "write");
			postMethod.addParameter("frob", frob);
			postMethod.addParameter("api_sig", getMD5Hash(authApiSig));

			int result = httpClient.executeMethod(postMethod);
			logger.debug(" [!] Post result >> " + result);
			logger.debug("[!] as string >> "
					+ postMethod.getResponseBodyAsString());

			// Post 설정
			BufferedReader infile = new BufferedReader(new InputStreamReader(
					System.in));
			String line = infile.readLine();
			try {
				Auth auth = authInterface.getToken(frob);
				System.out.println("Authentication success");
				// This token can be used until the user revokes it.
				System.out.println("Token: " + auth.getToken());
				System.out.println("nsid: " + auth.getUser().getId());
				System.out.println("Realname: " + auth.getUser().getRealName());
				System.out.println("Username: " + auth.getUser().getUsername());
				System.out.println("Permission: "
						+ auth.getPermission().getType());
			} catch (FlickrException e) {
				System.out.println("Authentication failed");
				e.printStackTrace();
			}

		} catch (Exception e) {

		}
	}

	public void getMD5(HttpServletRequest request, HttpServletResponse response) {

		try {
			response.setContentType("text/plain; charset=UTF-8");
			response.getOutputStream().write(
					(getMD5Hash(request.getParameter("value"))).getBytes());
		} catch (Exception e) {

		}

	}

	public void getToken(HttpServletRequest request,
			HttpServletResponse response) {

		try {

			response.setContentType("text/plain; charset=UTF-8");
			response.getOutputStream().write("".getBytes());

		} catch (Exception e) {

		}

	}

	public ModelAndView uploadForm(HttpServletRequest request,
			HttpServletResponse response) {

		String frob = request.getParameter("frob");

		ModelAndView mav = new ModelAndView();
		mav.addObject("frob", frob);
		mav.addObject("apiKey", API_KEY);
		mav.addObject("secretKey", SECRET_KEY);

		// 토큰을 구한다.
		String method = "flickr.auth.getToken";
		String apiSig = SECRET_KEY + "api_key" + API_KEY + "frob" + frob
				+ "method" + method;

		// URL 셋팅
		String url = "http://flickr.com/services/rest/?api_key=" + API_KEY
				+ "&frob=" + frob + "&method=" + method + "&api_sig="
				+ getMD5Hash(apiSig);

		// HttpClient 설정
		HttpClient httpClient = new HttpClient();

		// GetMethod 설정
		GetMethod getMethod = new GetMethod(url);

		try {
			// HttpClient 를 통해 GetMethod 를 실행
			int result = httpClient.executeMethod(getMethod);

			// TODO : HttpStatus 를 비교
			if (result > 0) {

				// Get the response body
				String responseBody = getMethod.getResponseBodyAsString();

				// TODO : 정규식으로 변경
				String token = responseBody.substring(responseBody
						.indexOf("token") + 6,
						responseBody.indexOf("/token") - 1);

				mav.addObject("token", token);
			}

		} catch (Exception e) {

		}

		return mav;
	}

	public void geAuthDestination(HttpServletRequest request,
			HttpServletResponse response) {

		try {

			String perms = "delete";
			String api_sig = SECRET_KEY + "api_key" + API_KEY + "perms" + perms;
			String dest = "http://flickr.com/services/auth/?api_key=" + API_KEY
					+ "&perms=" + perms + "&api_sig=" + getMD5Hash(api_sig);

			response.setContentType("text/plain; charset=UTF-8");
			response.getOutputStream().write(dest.getBytes());

		} catch (Exception e) {

		}

	}

	public ModelAndView uploadPhoto(HttpServletRequest request,
			HttpServletResponse response, FlickrModel flickr) {

		logger.debug("[!] uploadPhoto");

		// 리턴할 ModelAndView
		ModelAndView mav = new ModelAndView();

		String apiSig = SECRET_KEY + "api_key" + API_KEY + "auth_token"
				+ flickr.getAuth_token() + "content_type"
				+ flickr.getContent_type() + "description"
				+ flickr.getDescription() + "hidden" + flickr.getHidden()
				+ "is_family" + flickr.getIs_family() + "is_friend"
				+ flickr.getIs_friend() + "is_public" + flickr.getIs_public()
				+ "safety_level" + flickr.getSafety_level() + "tags"
				+ flickr.getTags() + "title" + flickr.getTitle();

		// HttpClient 설정
		HttpClient httpClient = new HttpClient();

		// HttpClient 에서 호출할 PostMethod 설정
		PostMethod uploadPhoto = new PostMethod(
				UzenOfficeConstants.FLICKR_UPLOAD_URL);

		StringPart[] sp = {
				new StringPart("api_key", API_KEY),
				new StringPart("auth_token", flickr.getAuth_token()),
				new StringPart("api_sig", flickr.getApi_sig()),
				new StringPart("title", flickr.getTitle()),
				new StringPart("description", flickr.getDescription()),
				new StringPart("tags", flickr.getTags()),
				new StringPart("is_public", Integer.toString(flickr
						.getIs_public())),
				new StringPart("is_friend", Integer.toString(flickr
						.getIs_friend())),
				new StringPart("is_family", Integer.toString(flickr
						.getIs_family())),
				new StringPart("safety_level", Integer.toString(flickr
						.getSafety_level())),
				new StringPart("content_type", Integer.toString(flickr
						.getContent_type())),
				new StringPart("hidden", Integer.toString(flickr.getHidden())) };

		try {
			// 파일에 관해 시험
			MultipartFile temp = flickr.getPhoto();
			logger.debug("[!] filename : " + temp.getName());
			logger.debug("[!] orignal Name : " + temp.getOriginalFilename());
			logger.debug("[!] fileSize : " + temp.getSize());

			// 파일 저장소
			File destinationDir = new File(UzenOfficeConstants.FILE_REPOSITORY);
			File destination = File.createTempFile(
					UzenOfficeConstants.FILENAME_PREFIX, temp
							.getOriginalFilename(), destinationDir);
			FileCopyUtils.copy(temp.getInputStream(), new FileOutputStream(
					destination));

			logger.debug("[!] getAbsoulutePath : "
					+ destination.getAbsolutePath());
			logger.debug("[!] getName : " + destination.getName());
			logger.debug("[!] getAbsoluteFile : "
					+ destination.getAbsoluteFile());

			File f = new File(destination.getAbsolutePath());
			FilePart fp = new FilePart("photo", f);
			fp.setCharSet("UTF-8");
			fp.setContentType("multipart/form-data");
			fp.setTransferEncoding("UTF-8");

			Part[] parts = {
					new StringPart("api_key", API_KEY, "UTF-8"),
					new StringPart("auth_token", flickr.getAuth_token(),
							"UTF-8"),
					new StringPart("api_sig", flickr.getApi_sig(), "UTF-8"),
					new StringPart("title", flickr.getTitle(), "UTF-8"),
					new StringPart("description", flickr.getDescription(),
							"UTF-8"),
					new StringPart("tags", flickr.getTags(), "UTF-8"),
					new StringPart("is_public", Integer.toString(flickr
							.getIs_public()), "UTF-8"),
					new StringPart("is_friend", Integer.toString(flickr
							.getIs_friend()), "UTF-8"),
					new StringPart("is_family", Integer.toString(flickr
							.getIs_family()), "UTF-8"),
					new StringPart("safety_level", Integer.toString(flickr
							.getSafety_level()), "UTF-8"),
					new StringPart("content_type", Integer.toString(flickr
							.getContent_type()), "UTF-8"),
					new StringPart("hidden", Integer.toString(flickr
							.getHidden()), "UTF-8"), fp };

			logger.debug(">> before setRequestEntity : "
					+ uploadPhoto.getParameters().length);
			uploadPhoto.setRequestEntity(new MultipartRequestEntity(parts,
					uploadPhoto.getParams()));
			logger.debug(">> after setRequestEntity : "
					+ uploadPhoto.getParameters().length);
			int index = 0;

			logger.debug(">> getParams <<");
			logger.debug(">> params.length : "
					+ uploadPhoto.getParameters().length);
			logger.debug(">> params : " + uploadPhoto.getParameters());

			for (NameValuePair pair : uploadPhoto.getParameters()) {

				logger.debug("[" + index++ + "] > " + pair.getName() + " : "
						+ pair.getValue());
			}

			logger.debug(">> end getParams <<");

			// HttpClient 를 통해 GetMethod 를 실행
			int result = httpClient.executeMethod(uploadPhoto);

			// TODO : HttpStatus 를 비교
			if (result > 0) {

				// Get the response body
				String responseBody = uploadPhoto.getResponseBodyAsString();

				// TODO : 정규식으로 변경
				String token = responseBody.substring(responseBody
						.indexOf("token") + 6,
						responseBody.indexOf("/token") - 1);

				mav.addObject("token", token);
				mav.addObject("responseBody", responseBody);
			}

		} catch (Exception e) {

		}

		return mav;
	}

	public ModelAndView blank(HttpServletRequest request,
			HttpServletResponse response) {

		return new ModelAndView();

	}
}
